package  
{
    import __AS3__.vec.Vector;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    import frocessing.color.ColorBlend;
    import frocessing.color.FColor;
    import frocessing.math.FMath;
    
    public class Attractor extends Sprite
    {
        protected var bmd: BitmapData;
        protected var isPlay: Boolean = true;
        protected var count: int;
		protected var maxden: int;
        protected var a: Number;
		protected var b: Number;
		protected var c: Number;
		protected var d: Number;
		protected var nx: Number;
		protected var ny: Number;
		protected var ox: Number;
		protected var oy: Number;
		protected var lmd: Number;
        protected var den: Vector.<Vector.<int>> = new Vector.<Vector.<int>>(465, true);
        protected var pre: Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(465, true);
        protected const sensitivity: Number = 0.0198411;
        protected const hueBase: int = 165;
        
        public function Attractor() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        protected function init(e: Event = null): void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            addChild(new Bitmap(bmd = new BitmapData(465, 465, false, 0x0), "auto", true));
            for (var i:int = 0; i < 465; i++) 
            {
                den[i] = new Vector.<int>(465, true);
                pre[i] = new Vector.<Number>(465, true);
            }
            reparam();
            addEventListener(Event.ENTER_FRAME, loop);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
            trace(hueBase);
        }
        
        protected function onMouseUp(e: MouseEvent): void 
        {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            isPlay = true;
            count = 0;
        }
        
        protected function onMouseDown(e: MouseEvent): void 
        {
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        }
        
        protected function onMouseMove(e: MouseEvent): void 
        {
            isPlay = false;
            reparam(mouseX, mouseY);
        }
        
        protected function reparam(mx: Number = 0, my: Number = 0): void
        {
            a = FMath.map(mx, 0, 456, -1, 1) * sensitivity;
            b = FMath.map(my, 0, 465, -1, 1) * sensitivity;
            c = FMath.map(mx, 0, 465, 1, -1) * sensitivity;
            d = FMath.map(my, 0, 465, 1, -1) * sensitivity;
            ox = oy = 465 / 2;
            update(true, 1, 100);
        }
        
        protected function loop(e: Event): void 
        {
            if (isPlay)
            {
                count++;
                if (count > 255) isPlay = false;
                update(false, 4, 0);
            }
        }
        
        protected function update(clear: Boolean, s: int, f: Number): void
        {
            var i: int;
			var j: int;
			var k: int;
			var e: int;
			var h_: Number;
			var s_: Number;
			var v_: Number;
			var le: Number;
			var col: uint;
			
			
            if (clear) for (i = 0; i < 465; i++) for (j = 0; j < 465; j++) den[i][j] = pre[i][j] = 0;
			
			
            for (i = 0; i < s; i++) 
			{ 
				for (j = 0; j < 10000; j++) 
				{
					nx = (((Math.sin(a * oy) - Math.cos(b * ox)) * 93) + 232.5) + Math.random() * 0.002 - 0.001;
					ny = (((Math.sin(c * ox) - Math.cos(d * oy)) * 93) + 232.5) + Math.random() * 0.002 - 0.001;
					if ( (nx > 0) && (nx < 465) && (ny > 0) && (ny < 465) )
					{
						if ((k = (den[int(nx)][int(ny)] += 1)) > maxden) maxden = k;
						pre[int(nx)][int(ny)] = ox;
					}
					ox = nx;
					oy = ny;
            	}
			}
            lmd = Math.log(maxden);
            bmd.lock();
            if (clear) bmd.fillRect(bmd.rect, 0x0);
            for (i = 0; i < 465; i++) 
			{ 
				for (j = 0; j < 465; j++)
				{
					if ((e = den[i][j]) > 0) 
						bmd.setPixel(i, j, 
							ColorBlend.soft(
								FColor.HSVtoValue(
									hueBase + hueBase * (pre[i][j] / 465), 
									0.5 - 0.5 * ((le = Math.log(e)) / lmd), 
									(le + f) / lmd), 
								bmd.getPixel(i, j)
							)
						);
            	}
			}
            bmd.unlock();
        }
    }
}